﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace PasteTimer.taskmodels
{

    /// <summary>
    /// 任务信息
    ///</summary>
    [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "view" })]
    public class TaskInfoAppService : IUserAppService
    {

        //private readonly IRepository<TaskInfo, int> _repository;

        private IPasteTimerDbContext _dbContext;
        private ModelHelper _modelHelper => LazyServiceProvider.LazyGetRequiredService<ModelHelper>();
        private ChannelHelper _channelHelper => LazyServiceProvider.LazyGetRequiredService<ChannelHelper>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbcontext"></param>
        public TaskInfoAppService(IPasteTimerDbContext dbcontext)
        {
            _dbContext = dbcontext;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="page"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        [HttpGet]
        [Obsolete]
        public async Task<PagedResultDto<TaskInfoListDto>> GetListAsync(int page = 1, int size = 20)
        {
            try
            {
                var _userid = base.ReadCurrentAdminId();
                var query_taskid = _dbContext.TaskBindUser.Where(x => x.UserId == _userid).Select(x => x.TaskId);
                var query = _dbContext.TaskInfo.Where(t => query_taskid.Contains(t.Id) || t.UserId == 0);
                var _pagedto = new PagedResultDto<TaskInfoListDto>();
                if (page == 1)
                {
                    _pagedto.TotalCount = await query.CountAsync();
                }
                var userList = await query.OrderByDescending(x => x.Id).Page(page, size).ToListAsync();
                var temList = ObjectMapper.Map<List<TaskInfo>, List<TaskInfoListDto>>(userList);
                _pagedto.Items = temList;
                return _pagedto;
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
            return null;
        }

        /// <summary>
        /// post形式的按页查询 支持状态等查询
        /// 只查询没人的和我的
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<PagedResultDto<TaskInfoListDto>> Page([FromQuery]InputQueryTaskModel input)
        {
            try
            {
                if (input.sdate != null)
                {
                    if (input.edate == null) { throw new PasteTimerException("请输入结束日期，进行任务日期的筛查！"); }
                }
                var _userid = base.ReadCurrentAdminId();
                var query_taskid = _dbContext.TaskBindUser.Where(x => x.UserId == _userid).Select(x => x.TaskId);
                var query = _dbContext.TaskInfo.Where(t => query_taskid.Contains(t.Id) || t.UserId == 0)
                    .WhereIf(input.state != -1, x => x.IsEnable == (input.state == 1))
                    .WhereIf(input.task_type != TaskType.Unknow, x => x.TaskType == input.task_type)
                    .WhereIf(input.sdate != null, x => input.sdate <= x.StartDate && x.StartDate < input.edate)
                    .WhereIf(!String.IsNullOrEmpty(input.group),x=>x.Groups.Contains(input.group))
                    .WhereIf(!string.IsNullOrEmpty(input.word), x => x.Name.Contains(input.word));
                var _pagedto = new PagedResultDto<TaskInfoListDto>();
                if (input.page == 1)
                {
                    _pagedto.TotalCount = await query.CountAsync();
                }
                var userList = await query.OrderBy(x => x.Groups).ThenBy(x=>x.StartDate).ThenBy(x=>x.Id).Page(input.page, input.size).ToListAsync();
                var temList = ObjectMapper.Map<List<TaskInfo>, List<TaskInfoListDto>>(userList);
                _pagedto.Items = temList;
                return _pagedto;
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
            return null;
        }

        /// <summary>
        /// 根据ID获取单项任务信息
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public TaskInfoDto GetByIdAsync(int id)
        {
            var _userid = base.ReadCurrentAdminId();

            var query = _dbContext.TaskInfo.Where(t => t.Id == id).FirstOrDefault();
            if (query.UserId != 0)
            {
                _modelHelper.HasTaskException(_dbContext, _userid, id);
            }
            var temList = ObjectMapper.Map<TaskInfo, TaskInfoDto>(query);
            return temList;
        }

        /// <summary>
        /// 根据ID获取待更新单项信息任务信息
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public TaskInfoUpdateDto GetInfoForUpdateAsync(int id)
        {
            var _userid = base.ReadCurrentAdminId();
            var query = _dbContext.TaskInfo.Where(t => t.Id == id).FirstOrDefault();
            if (query.UserId != 0)
            {
                _modelHelper.HasTaskException(_dbContext, _userid, id);
            }
            var temList = ObjectMapper.Map<TaskInfo, TaskInfoUpdateDto>(query);
            return temList;
        }


        /// <summary>
        /// 添加一个任务信息
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork(false)]
        [HttpPost]
        public async Task<TaskInfoDto> CreateItemAsync(TaskInfoAddDto input)
        {
            var _userid = base.ReadCurrentAdminId();
            var newu = ObjectMapper.Map<TaskInfoAddDto, TaskInfo>(input);
            newu.FileVersion = 1000;
            if (input.TickRegex.Contains("*"))
            {
                newu.TaskType = TaskType.OnTime;
                newu.TickSecond = 0;
            }
            else
            {
                _modelHelper.ReadTickSecond(newu);
            }
            try
            {
                _dbContext.Database.BeginTransaction();
                newu.UserId = _userid;
                _dbContext.Add(newu);
                _dbContext.SaveChanges();
                _dbContext.Add(new TaskBindUser
                {
                    CreateDate = DateTime.Now,
                    Create_UserId = _userid,
                    TaskId = newu.Id,
                    UserId = _userid
                });
                await _dbContext.SaveChangesAsync();
                var backinfo = ObjectMapper.Map<TaskInfo, TaskInfoDto>(newu);
                _channelHelper.WriteStatus(new StatusModel() { Action = 1, ModelType = 1, body = Newtonsoft.Json.JsonConvert.SerializeObject(backinfo) });
                _dbContext.Database.CommitTransaction();
                return backinfo;
            }
            catch (Exception exl)
            {
                _dbContext.Database.RollbackTransaction();
                Logger.LogException(exl);
                throw;
            }
        }

        /// <summary>
        /// 更新一个任务信息
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<TaskInfoDto> UpdateItemAsync(TaskInfoUpdateDto input)
        {
            var info = await _dbContext.TaskInfo.Where(x => x.Id == input.Id).FirstOrDefaultAsync();
            if (info == null || info == default)
            {
                throw new UserFriendlyException("需要查询的信息不存在", "404");
            }
            var _userid = base.ReadCurrentAdminId();
            if (info.UserId != 0)
            {
                _modelHelper.HasTaskException(_dbContext, _userid, info.Id);
            }
            if (info.AssemblyZip != input.AssemblyZip)
            {
                info.FileVersion++;
            }
            ObjectMapper.Map<TaskInfoUpdateDto, TaskInfo>(input, info);
            if (input.TickRegex.Contains("*"))
            {
                info.TaskType = TaskType.OnTime;
                info.TickSecond = 0;
            }
            else
            {
                _modelHelper.ReadTickSecond(info);
            }
            await _dbContext.SaveChangesAsync();
            var backinfo = ObjectMapper.Map<TaskInfo, TaskInfoDto>(info);
            _channelHelper.WriteStatus(new StatusModel() { Action = 2, ModelType = 1, body = Newtonsoft.Json.JsonConvert.SerializeObject(backinfo) });
            return backinfo;
        }

        ///// <summary>
        ///// 计算轮询秒数
        ///// </summary>
        ///// <param name="info"></param>
        ///// <exception cref="Exception"></exception>
        //private void ReadTickSecond(TaskInfo info)
        //{
        //    if (!string.IsNullOrEmpty(info.TickRegex))
        //    {
        //        if (info.TickRegex.Length == 8)
        //        {
        //            var timesplit = info.TickRegex.Split(":");
        //            if (timesplit.Length == 3)
        //            {
        //                int.TryParse(timesplit[0], out var hour);
        //                int.TryParse(timesplit[1], out var min);
        //                int.TryParse(timesplit[2], out var sec);
        //                info.TickSecond = (hour * 3600) + (min * 60) + sec;
        //                info.TaskType = TaskType.Tick;
        //            }
        //        }
        //    }
        //}

        /// <summary>
        /// 删除一个任务信息，真删除
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<int> DeleteItemById(int id)
        {
            var info = await _dbContext.TaskInfo.Where(xy => xy.Id == id).FirstOrDefaultAsync();//.FirstOrDefault();
            if (info != default)
            {
                var _userid = base.ReadCurrentAdminId();
                if (info.UserId != 0)
                {
                    _modelHelper.HasTaskException(_dbContext, _userid, id);
                }
                _dbContext.Remove(info);
                await _dbContext.SaveChangesAsync();
                _channelHelper.WriteStatus(new StatusModel() { Action = 3, ModelType = 1, body = $"{id}" });
            }
            return 1;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<int> UpdateState(int id, bool state)
        {
            var info = await _dbContext.TaskInfo.Where(xy => xy.Id == id).FirstOrDefaultAsync();//.FirstOrDefault();
            if (info != default)
            {
                var _userid = base.ReadCurrentAdminId();
                if (info.UserId != 0)
                {
                    _modelHelper.HasTaskException(_dbContext, _userid, id);
                }
                info.IsEnable = state;
                await _dbContext.SaveChangesAsync();
                var dto = ObjectMapper.Map<TaskInfo, TaskInfoDto>(info);
                _channelHelper.WriteStatus(new StatusModel() { Action = 2, ModelType = 1, body = Newtonsoft.Json.JsonConvert.SerializeObject(dto) });
            }
            return 1;
        }

        /// <summary>
        /// 对一个任务执行调用，请注意确保调用端是否允许重复调用等
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> Test(int id)
        {
            var info = await _dbContext.TaskInfo.Where(xy => xy.Id == id).AsNoTracking().FirstOrDefaultAsync();//.FirstOrDefault();
            if (info != default)
            {
                var _userid = base.ReadCurrentAdminId();
                if (info.UserId != 0)
                {
                    _modelHelper.HasTaskException(_dbContext, _userid, id);
                }
                var dto = ObjectMapper.Map<TaskInfo, TaskInfoDto>(info);
                _channelHelper.WriteSlaveAction(new SlaveEventModel() { Event= "testtask", Object=Newtonsoft.Json.JsonConvert.SerializeObject(dto) });
                return "测试任务已经发布，请等待并查看执行记录！";
            }
            return "没有找到这样的任务，无法执行测试！";
        }

    }
}
